/**
 * Copyright (C) 2011 KingCore Science & Technology CO,.LTD. All rights reserved.
 * XNS PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

/**
 * Copyright (C) 2002-2011 WUZEWEN. All rights reserved.
 * WUZEWEN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 * This software is the confidential and proprietary information of
 * WuZeven, Personal. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with WuZeven.
 */

package com.kingcore.director.search.ui;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;

import org.apache.log4j.Logger;
import org.apache.lucene.document.Document;

import com.kingcore.director.core.util.StopWatch;
import com.kingcore.director.main.MainFrame;
import com.kingcore.director.search.concurrent.DataListConsumer;
import com.kingcore.director.search.concurrent.FileConsumerDataListProducer;
import com.kingcore.director.search.concurrent.FileProducer;

/**
 * <p>java class file describe</p>
 * @author Zeven on 2011-3-18
 * @version	1.0
 * @see		Object#equals(java.lang.Object)
 * @since	JDK5
 */

public class LocalFileIndexEngine {

	//log object
	private final static Logger log = Logger.getLogger(LocalFileIndexEngine.class);
	MainFrame mainFrame = null;
	public LocalFileIndexEngine(MainFrame mainFrame) {
		this.mainFrame = mainFrame ;
	}

	/**
	 * <p>java method describe</p>
	 * @author Zeven on 2011-3-18
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}
	
	static StopWatch sw = new StopWatch();
	 private static Map<File, String> localFileSearchExcludedFileMap = new HashMap<File, String>();

	 /**
	  * 
	  * <p>本方法完成磁盘全面检索，本类其他的方法为支持老版本的索引更新而保留。</p>
	  * @author Zeven on 2011-3-18
	  */
	public void refreshAllLocalFile() { 
		
		//---------------  生产者消费者模式
        BlockingQueue<File> fielQueue = new LinkedBlockingQueue<File>(300);
        BlockingQueue<List<Map<String,String>>> dataListqueue = new LinkedBlockingQueue<List<Map<String,String>>>(2); //写索引慢，2个够了，堆多了也没用。

        FileProducer fileProducer = new FileProducer(fielQueue);
        FileConsumerDataListProducer fileConsumer = new FileConsumerDataListProducer(fielQueue, dataListqueue);
        DataListConsumer dataListConsumer = new DataListConsumer(dataListqueue, mainFrame);

        // 借助Executors
        ExecutorService service = Executors.newCachedThreadPool();
        // 启动线程
        service.execute(fileProducer);
        service.execute(fileConsumer);
        service.execute(dataListConsumer);

		//---------------  生产者消费者模式 end 
//		sw.start();
//		Connection conn= null;
//		Statement stmt =null;
//		ResultSet rs=null;
//		try {
//			conn= ApplicationContext.getInstance().getDataSourceManager().getConnection();
//			stmt=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
//			rs=stmt.executeQuery("SELECT val from "+DirectorConstants.SYS_Setting+" WHERE KEY='"
//								+ DirectorConstants.Local_File_Search_Excluded +"'");
//			while (rs.next()) {
//				localFileSearchExcludedFileMap.put(new File(rs.getString("val")), "val");
//			}			
//		} catch (Exception e){
//			log.error (e);
//		} finally {
//			wzw.util.DbUtils.closeQuietly(conn, stmt, rs);
//		}	
//
//		log.info( sw.watchPoint() );
//		long startTime = System.currentTimeMillis();
//		File roots[] = File.listRoots();    // 得到本地机的磁盘驱动(根)，并将其放入到一个File数组中
//		String root = null;
//		String filename[] = null;
//
//		log.info( sw.watchPoint() );
//		ib = LocalFileIndexBuilder.getInstance(LocalFileIndexBuilder.ANALYZER, LocalFileIndexBuilder.LocalFileSystem_INDEX, true);
//			
//		log.info( sw.watchPoint() );
//		for (int j = 0; j < roots.length; j++) {
////			if (j!=3) {  // just for debug
////				continue;
////			}
//			root = roots[j].toString();
////			root = "F:/Downloads";    // just for debug
//			log.info("begin create:"+root);
//
//			log.info( sw.watchPoint() );
//			File fileDir = new File(root);
//			if (localFileSearchExcludedFileMap.get(fileDir)!=null) { // excluded
//				log.info(fileDir.getAbsolutePath()+" excluded.");
//				continue;
//			}
//			filename = fileDir.list();// 获得跟目录下的所有的文件名或子目录名;(只是文件夹名或文件名，不是其结对路径)
//			if (filename != null) { // 判断跟目录下是否有文件夹或子目录；
//				try {
//					log.info( sw.watchPoint() );
//					loopFiles(fileDir.getAbsolutePath(), filename, "create"); // 传递的两个参数，前一个代表父目录，后一个为list()总的文件名
//					addFile2List(null, "create");
//					
//				} catch (Exception e) {
//					e.printStackTrace();
//					log.error(e);
//				}
//			}
//			log.info("creating index file finished,file count is:" + count );
//		}
//		ib.close();
//		//LocalFileIndexBuilder.getInstance(LocalFileIndexBuilder.ANALYZER, LocalFileIndexBuilder.LocalFileSystem_INDEX, true).close();
//		double allTime = ((float)(System.currentTimeMillis()-startTime))/(60000.00);
//		DecimalFormat df = new DecimalFormat("0.000");//格式化小数，不足的补0
//		String allTimeStr = df.format(allTime);//返回的是String类型的
//		String info = "Success!" +" Index files were created,file count is:" + count 
//					+ ",took time "+ allTimeStr+ " minutes";
//		log.info(info); 
	
	}


	 private static int count=0;
	 private static List<Map<String,String>>  fileList = new ArrayList<Map<String,String>>();
	 
	public static void loopFiles(String parent, String[] sd, String action) throws Exception { // 这是一个递归调用的，遍历各个文件夹

		String[] s = sd;
		if (s != null) {
			for (int i = 0; i < s.length; i++) { 
				File f = new File(parent + File.separator + s[i]); // 这里的“\\”很重要，否则f.getAbsolutePath()
				if (localFileSearchExcludedFileMap.get(f)!=null) { // excluded
					log.info(f.getAbsolutePath()+" excluded.");
					log.info( sw.watchPoint() );
					continue;
				}
				if (f.isDirectory()) {
					Map<String,String> map = new HashMap<String,String>();
					map.put("name", f.getName());
					map.put("path", f.getParent()); //f.getAbsolutePath()
					map.put("size", "");
					map.put("lastModifiedTime", f.lastModified()+"");
					addFile2List(map, action);

					String[] ss = f.list();
					loopFiles(f.getAbsolutePath(), ss, action);// 递归调用；

				} else {
					//System.out.println(f.getAbsolutePath());
					count++;
					Map<String,String> map = new HashMap<String,String>();
					map.put("name", f.getName());
					map.put("path", f.getParent()); //f.getAbsolutePath()
					map.put("size", f.length()+"");
					map.put("lastModifiedTime", f.lastModified()+"");
					addFile2List(map, action); 
				}
			}
		}

	}
	
	public static LocalFileIndexBuilder ib = null;
	private static Thread writeIndexThread = null;
	private static boolean isIndexBuilderInit = false;
	
	 private static void addFile2List(Map<String,String> map, String action) throws Exception{
		if ("delete".equals(action)) {  //delete index file
			LocalFileIndexManager im = new LocalFileIndexManager(LocalFileIndexBuilder.LocalFileSystem_INDEX);
			im.deleteIndexByIndex( map.get("path") + File.separator + map.get("name") );
			im.close();
			return ;
		}
			
		if (map != null) {
			fileList.add(map);
		}
		if (map == null || fileList.size() == FileConsumerDataListProducer.Batch_Size_Write_To_Document) {
			if (writeIndexThread!=null) {
				writeIndexThread.join(); //waiting until thread completed.
			}
			final List<Map<String,String>> tmp_fileList = fileList;
			fileList = new ArrayList<Map<String,String>>();
//			log.info( sw.watchPoint() );
			
			//3th parameter boolean:true to create the index or overwrite the existing one; false to append to the existing index 
			if (isIndexBuilderInit==false) {
				//ib.init(LocalFileIndexBuilder.LocalFileSystem_INDEX);
				isIndexBuilderInit=true;
			}

			log.info("begin write to index file...");
			writeIndexThread = new Thread(){
				public void run() {
					List<Document> documentList = DataListConsumer.convertToDocumentList(tmp_fileList);
					ib.writeToIndex(documentList);
			  }
			};
			log.info("start new thread to write to index file...");
			writeIndexThread.start(); //start a new thread to write index files.
			// 写所有文件应该是不支持并发的，故只能一个线程做。磁盘文件遍历，是否可以多加线程？？
				
			log.info( sw.watchPoint() );
		}
	 }
	 
}
